From: Jan Beulich Date: Tue, 2 Jul 2013 06:41:28 +0000 (+0200) Subject: x86/xsave: adjust state management X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~6676 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=f9755488bf17c056111d1e442be394cfb63d7788;p=xen.git x86/xsave: adjust state management The initial state for a vCPU is using default values, so there's no need to force the XRSTOR to read the state from memory. This saves a couple of thousand restores from memory just during boot of Linux on my Sandy Bridge system (I didn't try to make further measurements). The above requires that arch_set_info_guest() updates the state flags in the save area when valid floating point state got passed in, but that would really have been needed even before in case XSAVE{,OPT} decided to clear one or both of the FP and SSE bits. Furthermore, hvm_vcpu_reset_state() shouldn't just clear out the FPU/ SSE area, but needs to re-initialized MXCSR and FCW. Signed-off-by: Jan Beulich Acked-by: Keir Fraser --- diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 52c9040f59..874742c3b1 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -712,7 +712,11 @@ int arch_set_info_guest( v->arch.vgc_flags = flags; if ( flags & VGCF_I387_VALID ) + { memcpy(v->arch.fpu_ctxt, &c.nat->fpu_ctxt, sizeof(c.nat->fpu_ctxt)); + if ( v->arch.xsave_area ) + v->arch.xsave_area->xsave_hdr.xstate_bv = XSTATE_FP_SSE; + } if ( !compat ) { diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 43b6d052ba..1fcaed0b83 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -3466,6 +3466,7 @@ void hvm_vcpu_reset_state(struct vcpu *v, uint16_t cs, uint16_t ip) { struct domain *d = v->domain; struct segment_register reg; + typeof(v->arch.xsave_area->fpu_sse) *fpu_ctxt = v->arch.fpu_ctxt; domain_lock(d); @@ -3479,7 +3480,12 @@ void hvm_vcpu_reset_state(struct vcpu *v, uint16_t cs, uint16_t ip) v->arch.guest_table = pagetable_null(); } - memset(v->arch.fpu_ctxt, 0, sizeof(v->arch.xsave_area->fpu_sse)); + memset(fpu_ctxt, 0, sizeof(*fpu_ctxt)); + fpu_ctxt->fcw = FCW_RESET; + fpu_ctxt->mxcsr = MXCSR_DEFAULT; + if ( v->arch.xsave_area ) + v->arch.xsave_area->xsave_hdr.xstate_bv = XSTATE_FP; + v->arch.vgc_flags = VGCF_online; memset(&v->arch.user_regs, 0, sizeof(v->arch.user_regs)); v->arch.user_regs.eflags = 2; diff --git a/xen/arch/x86/xstate.c b/xen/arch/x86/xstate.c index d52dbd715c..608accfe48 100644 --- a/xen/arch/x86/xstate.c +++ b/xen/arch/x86/xstate.c @@ -204,9 +204,13 @@ int xstate_alloc_save_area(struct vcpu *v) if ( save_area == NULL ) return -ENOMEM; + /* + * Set the memory image to default values, but don't force the context + * to be loaded from memory (i.e. keep save_area->xsave_hdr.xstate_bv + * clear). + */ save_area->fpu_sse.fcw = FCW_DEFAULT; save_area->fpu_sse.mxcsr = MXCSR_DEFAULT; - save_area->xsave_hdr.xstate_bv = XSTATE_FP_SSE; v->arch.xsave_area = save_area; v->arch.xcr0 = XSTATE_FP_SSE; diff --git a/xen/include/asm-x86/xstate.h b/xen/include/asm-x86/xstate.h index 49168f3293..dc3cb8eb75 100644 --- a/xen/include/asm-x86/xstate.h +++ b/xen/include/asm-x86/xstate.h @@ -11,6 +11,7 @@ #include #define FCW_DEFAULT 0x037f +#define FCW_RESET 0x0040 #define MXCSR_DEFAULT 0x1f80 #define XSTATE_CPUID 0x0000000d